import os
from configparser import ConfigParser, MissingSectionHeaderError
from ..models.tools import Tool
from ..models.versions import Version

ConfigMap = {}


def _read_config(file_path):
    cfg = ConfigParser()
    try:
        try:
            cfg.read(file_path, encoding="utf-8")
        except UnicodeDecodeError as e:
            cfg.read(file_path, encoding="GBK")
        except MissingSectionHeaderError as e:
            BOM = b'\xef\xbb\xbf'
            existBom = lambda s: True if s == BOM else False
            f = open(file_path, 'rb')
            if existBom(f.read(3)):
                fbody = f.read()
                # f.close()
                with open(file_path, 'wb') as f:
                    f.write(fbody)
            cfg.read(file_path, encoding="utf-8")
    except Exception as e:
        print(str(e))
    return cfg


def tools2db(tools, file_path):
    dir_path = os.path.dirname(file_path)
    dir_name = os.path.basename(dir_path)
    updated = []
    deleted = []
    rows = Tool.query.filter_by(path=dir_path).all()
    for row in rows:
        if row.name not in tools and row.name != dir_name:
            deleted.append(row)
            deleted += row.versions.all()
        elif row.name in tools:
            attrs = tools[row.name]
            row.description = attrs.get('description', '')
            version = row.versions.first()
            if version:
                version.is_latest = True
                version.tool_name = attrs.get('exe', '')
                version.version = attrs.get('version', '')
            else:
                version = Version(attrs.get('version', ''), tool_name=attrs.get('exe', ''), is_latest=True,
                                  tool=row)
            updated = updated + [row, version]
            tools.pop(row.name)
    for k, v in tools.items():
        tool = Tool(name=k, description=v.get('description', ''), path=dir_path)
        version = Version(version=v.get('version', ''), tool_name=v.get('exe', ''), is_latest=True, tool=tool)
        updated = updated + [tool, version]
    return updated, deleted


def parse_tools(file_path):
    cfg = _read_config(file_path)
    if not cfg:
        return [], []
    else:
        if file_path in ConfigMap and cfg == ConfigMap[file_path]:
            return [], []
        ConfigMap[file_path] = cfg
    # 读取tools的config
    config_tools = {cfg.get(i, 'name', fallback=""): dict(cfg.items(i)) for i in cfg.sections()}
    config_tools.pop("") if '' in config_tools else None
    # 获取tools的变更
    result = tools2db(config_tools, file_path)
    return result


def versions2db(settings, versions, file_path):
    updated = []
    deleted = []
    dir_path = os.path.dirname(file_path)
    dir_name = os.path.basename(dir_path)
    latest = settings.get("latest", '')
    tool = Tool.query.filter_by(name=dir_name).first()
    if tool:
        rows = tool.versions.all()
        if not versions or not settings:
            deleted += rows
            deleted.append(tool)
    else:
        tool = Tool(name=dir_name, path=dir_path)
        rows = []
        if not versions or not settings:
            return [], []

    for row in rows:
        if row.version not in versions:
            deleted.append(row)
        else:
            row.is_latest = True if row.version == latest else False
            row.tool_name = versions[row.version]
            updated.append(row)
            versions.pop(row.version)
    if rows and len(rows) == len(deleted):
        deleted.append(tool)
    else:
        for k, v in versions.items():
            version = Version(version=k, tool_name=v, is_latest=True if k == latest else False, tool=tool)
            updated = updated + [version]
        tool.description = settings.get("description", '')
        tool.other_files = settings.get("others", '')
        updated.append(tool)
    return updated, deleted


def parse_versions(file_path):
    cfg = _read_config(file_path)
    if not cfg:
        return [], []
    else:
        if file_path in ConfigMap and cfg == ConfigMap[file_path]:
            return [], []
        ConfigMap[file_path] = cfg
    # 读取versions的数据库
    settings = dict(cfg.items('setting')) if 'setting' in cfg.sections() else {}
    config_versions = dict(cfg.items('versions')) if 'versions' in cfg.sections() else {}

    # 获取versions的变更
    result = versions2db(settings, config_versions, file_path)

    return result
